# package pgp

# import (
# 	"errors"
# 	"os/exec"
# 	"regexp"
# )


# // GPGVersion stores discovered GPG version
GPGVersion=int

# // GPG version as discovered
# const (
# from enum import Enum
from typing import List,Dict,Tuple

GPG1x      :GPGVersion = 1
GPG20x     :GPGVersion = 2
GPG21x     :GPGVersion = 3
GPG22xPlus :GPGVersion = 4
# )

# // GPGFinder implement search for gpg executables and returns version of discovered executables
class GPGFinder:

	def FindGPG(self):# (gpg string, version GPGVersion, err error)
		pass
	def FindGPGV(self):# (gpgv string, version GPGVersion, err error)
		pass
# }

class pathGPGFinder(GPGFinder):
	gpgNames     :List[str]
	gpgvNames    :List[str]
	errorMessage :str

	expectedVersionSubstring :str
	def FindGPG(pgf) -> Tuple [ str,  GPGVersion,  str]:
		gpg=None
		version=None
		err=None
		for  cmd in pgf.gpgNames :
			result :bool=None
			result, version = cliVersionCheck(cmd, pgf.expectedVersionSubstring)
			if result :
				gpg = cmd
				break
			
		

		if gpg is None :
			err = (pgf.errorMessage)
		

		return  gpg,version,err
	

	def  FindGPGV(pgf) ->Tuple [ str,  GPGVersion,  str] :
		gpgv=None
		version=None
		err=None
		for  cmd in pgf.gpgvNames :
			result :bool=None
			result, version = cliVersionCheck(cmd, pgf.expectedVersionSubstring)
			if result :
				gpgv = cmd
				break
			
		

		if gpgv == "" :
			err = (pgf.errorMessage)
		

		return gpgv,version,err
	


class iteratingGPGFinder(GPGFinder):
	finders      :List[GPGFinder]=[]
	errorMessage :str

	def  FindGPG(it)->Tuple [str,  GPGVersion,  str] :
		gpg=None
		version=None
		err=None
		for   finder in it.finders :
			gpg, version, err = finder.FindGPG()
			if err is None  :
				return gpg, version, err
		
		

		err = it.errorMessage

		return gpg,version,err
	

	def FindGPGV(it)->Tuple [str,  GPGVersion,  str] :
		gpgv=None
		version=None
		err=None
		for   finder in it.finders :
			gpgv, version, err = finder.FindGPGV()
			if err is None  :
				return gpgv,version,err
			
		

		err =  (it.errorMessage)

		return gpgv,version,err
	

# // GPGDefaultFinder looks for GPG1 first, but falls back to GPG2 if GPG1 is not available
def GPGDefaultFinder() ->GPGFinder :
	iteratingGPGFinderObj=iteratingGPGFinder()
	iteratingGPGFinderObj.finders=[GPG1Finder(), GPG2Finder()]
	iteratingGPGFinderObj.errorMessage="Couldn't find a suitable gpg executable. Make sure gnupg is installed"
	return iteratingGPGFinderObj


	


# // GPG1Finder looks for GnuPG1.x only
def GPG1Finder() ->GPGFinder :
	pathGPGFinderObj=pathGPGFinder()
	pathGPGFinderObj.gpgNames= ["gpg", "gpg1"]
	pathGPGFinderObj.gpgvNames= ["gpgv", "gpgv1"]
	pathGPGFinderObj.expectedVersionSubstring= '\(GnuPG(.*)\) 1\.(\d).(\d+)'
	pathGPGFinderObj.errorMessage= "Couldn't find a suitable gpg executable. Make sure gnupg1 is available as either gpg(v) or gpg(v)1 in $PATH"
	return pathGPGFinderObj

# // GPG2Finder looks for GnuPG2.x only
def GPG2Finder()-> GPGFinder :
	pathGPGFinderObj=pathGPGFinder()
	pathGPGFinderObj.gpgNames= ["gpg", "gpg2"]
	pathGPGFinderObj.gpgvNames= ["gpgv", "gpgv2"]
	pathGPGFinderObj.expectedVersionSubstring= '\(GnuPG(.*)\) 2\.(\d)\.(\d+)'
	pathGPGFinderObj.errorMessage= "Couldn't find a suitable gpg executable. Make sure gnupg2 is available as either gpg(v) or gpg(v)2 in $PATH"
	return pathGPGFinderObj
	
	


import re,os
def cliVersionCheck(cmd :str, marker :str) ->Tuple[ bool,  GPGVersion] :
	output = os.popen( "{} --version".format(cmd)).readline()
	
	# if err is not None  :
	# return
	strOutput = output
	
	regex = re.compile(marker)

	version = GPG22xPlus
	matches = regex.findall(strOutput)
	
	result =False
	if(len(matches)):
		matches =matches[0]
		result =True
	if matches is not None  and  len(matches):
		if matches[1] == "1" :
			version = GPG1x
		elif matches[1] == "2" and matches[2] == "0" :
			version = GPG20x
		elif matches[1] == "2" and matches[2] == "1" :
			version = GPG21x
	# return
	return result,version
# }
